﻿using System;
using System.Linq.Expressions;
using System.Collections.Generic;
using System.Runtime.Serialization;

namespace QbservableCore.Serialization
{
    [DataContract]
    public class BinaryNode : ExpRepresentationBase
    {
        [DataMember]
        public ExpRepresentationBase Left { get; set; }

        [DataMember]
        public ExpRepresentationBase Right { get; set; }

        private int OperatorValue { get; set; }

        [DataMember]
        public ExpressionType Operator
        {
            get
            {
                return (ExpressionType)OperatorValue;
            }
            set
            {
                OperatorValue = (int)value;
            }
        }

        protected internal override Expression ToExpression(ExepressionBuilderCache exepressionBuilderCache)
        {
            var left = Left.ToExpression(exepressionBuilderCache);
            var right = Right.ToExpression(exepressionBuilderCache);
            return Expression.MakeBinary(Operator, left, right);
        }

        protected override void TraverseChildren(Func<ExpRepresentationBase, ExpRepresentationBase> action)
        {
            Left = Left.Traverse(action);
            Right = Right.Traverse(action);
        }

        public override string ToString()
        {
            string opr = GetOperator(Operator);
            return string.Format("{0} {1} {2}", Left, opr, Right);
        }

        private string GetOperator(ExpressionType opr)
        {
            switch (opr)
            {
                case ExpressionType.Add:
                    return "+";
                case ExpressionType.And:
                    return "&";
                case ExpressionType.AndAlso:
                    return "&&";
                case ExpressionType.Divide:
                    return "/";
                case ExpressionType.Equal:
                    return "==";
                case ExpressionType.ExclusiveOr:
                    return "^";
                case ExpressionType.GreaterThan:
                    return ">";
                case ExpressionType.GreaterThanOrEqual:
                    return ">=";
                case ExpressionType.LeftShift:
                    return "<<";
                case ExpressionType.LessThan:
                    return "<";
                case ExpressionType.LessThanOrEqual:
                    return "<=";
                case ExpressionType.Modulo:
                    return "%";
                case ExpressionType.Multiply:
                    return "*";
                case ExpressionType.NotEqual:
                    return "!=";
                case ExpressionType.Or:
                    return "|";
                case ExpressionType.OrElse:
                    return "||";
                case ExpressionType.RightShift:
                    return ">>";
                case ExpressionType.Subtract:
                    return "-";
                default:
                    return "<???>";
            }
        }
    }
}